﻿using AJWPFAdmin.Core;
using AJWPFAdmin.Core.Components.AJFilePicker.ViewModels;
using AJWPFAdmin.Core.Components.AJTable.ViewModels;
using AJWPFAdmin.Core.Components.ViewModels;
using AJWPFAdmin.Core.Components.Views;
using AJWPFAdmin.Core.Enums;
using AJWPFAdmin.Core.Excel;
using AJWPFAdmin.Core.ExtensionMethods;
using AJWPFAdmin.Core.Models;
using AJWPFAdmin.Core.Models.EF.Tables;
using AJWPFAdmin.Core.Utils;
using AJWPFAdmin.Core.Validation;
using AJWPFAdmin.Services.AppointAPI;
using AJWPFAdmin.Services.EF;
using AJWPFAdmin.Services.EF.TableExts;
using AJWPFAdmin.Services.Models;
using AngleSharp.Common;
using FFmpeg.AutoGen;
using Masuit.Tools;
using Masuit.Tools.Reflection;
using Masuit.Tools.Systems;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using Prism.Commands;
using Prism.Events;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using Yitter.IdGenerator;
using static AJWPFAdmin.Core.ExceptionTool;

namespace EntranceGuardManager.Modules.Main.ViewModels
{
    public class CarFormTemplateSelector : DataTemplateSelector
    {
        public DataTemplate TaiZhangForm { get; set; }
        public DataTemplate FactoryForm { get; set; }
        public DataTemplate MachineForm { get; set; }
        public DataTemplate TempForm { get; set; }

        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            if (item is AJTableFormSchemaItemOptions option)
            {
                var type = (CarTypeEnum)(Convert.ToInt32((long)option.Value));

                switch (type)
                {
                    case CarTypeEnum.固定车:
                    case CarTypeEnum.进出厂车:
                        return TaiZhangForm;
                    case CarTypeEnum.厂内运输车:
                        return FactoryForm;
                    case CarTypeEnum.非道路移动机械:
                        return MachineForm;
                    case CarTypeEnum.临时车:
                    case CarTypeEnum.免检车:
                        return TempForm;
                    default:
                        break;
                }

            }
            return TempForm;
        }
    }

    public class CarTypeVisibilityConvert : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null)
            {
                return Visibility.Collapsed;
            }

            var type = (AJTableFormSchemaItemOptions)value;

            return type.Label == "台账车" ? Visibility.Visible : Visibility.Collapsed;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return null;
        }
    }

    public class CarFormViewModel : AnnotationValidationViewModel, IDialogAware
    {
        private string _dialogTitle;
        public string DialogTitle
        {
            get { return _dialogTitle; }
            set { SetProperty(ref _dialogTitle, value); }
        }

        private bool _loading;
        public bool Loading
        {
            get { return _loading; }
            set { SetProperty(ref _loading, value); }
        }

        private bool _synchronized;
        public bool Synchronized
        {
            get { return _synchronized; }
            set { SetProperty(ref _synchronized, value); }
        }

        private string _syncResult;
        public string SyncResult
        {
            get { return _syncResult; }
            set { SetProperty(ref _syncResult, value); }
        }

        private Car _form;

        private string _inGoodsName;
        /// <summary>
        /// 进厂运输货物名称
        /// </summary>
        [Display(Name = "进厂运输货物")]
        [StringLength(200, ErrorMessage = "{0}超长:{1}")]
        public string InGoodsName
        {
            get
            {
                return _inGoodsName;
            }
            set
            {
                SetProperty(ref _inGoodsName, value);
            }
        }

        private decimal _inGoodsVolume;
        /// <summary>
        /// 进厂运输量
        /// </summary>
        public decimal InGoodsVolume
        {
            get
            {
                return _inGoodsVolume;
            }
            set
            {
                SetProperty(ref _inGoodsVolume, value);
            }
        }

        private string _outGoodsName;
        /// <summary>
        /// 出厂运输货物名称
        /// </summary>
        [Display(Name = "出厂运输货物")]
        [StringLength(200, ErrorMessage = "{0}超长:{1}")]
        public string OutGoodsName
        {
            get
            {
                return _outGoodsName;
            }
            set
            {
                SetProperty(ref _outGoodsName, value);
            }
        }

        private decimal _outGoodsVolume;
        /// <summary>
        /// 出厂运输量
        /// </summary>
        public decimal OutGoodsVolume
        {
            get
            {
                return _outGoodsVolume;
            }
            set
            {
                SetProperty(ref _outGoodsVolume, value);
            }
        }

        private string _verifiedLoadWeight;
        /// <summary>
        /// 核定载重质量
        /// </summary>
        public string VerifiedLoadWeight
        {
            get
            {
                return _verifiedLoadWeight;
            }
            set
            {
                SetProperty(ref _verifiedLoadWeight, value);
            }
        }

        private string _permittedTowingWeight;
        /// <summary>
        /// 准牵引总质量
        /// </summary>
        public string PermittedTowingWeight
        {
            get
            {
                return _permittedTowingWeight;
            }
            set
            {
                SetProperty(ref _permittedTowingWeight, value);
            }
        }

        private List<Goods> _goodsSrouce;
        private ObservableCollection<string> _goodsOptions;
        public ObservableCollection<string> GoodsOptions
        {
            get => _goodsOptions;
            set
            {
                SetProperty(ref _goodsOptions, value);
            }
        }

        private UploadConfig _uploadOptions;
        public UploadConfig UploadOptions
        {
            get
            {
                return _uploadOptions;
            }
            set
            {
                SetProperty(ref _uploadOptions, value);
            }
        }

        private ObservableCollection<UploadFileItem> _attachments;
        public ObservableCollection<UploadFileItem> Attachments
        {
            get { return _attachments; }
            set
            {
                SetProperty(ref _attachments, value);
            }
        }

        private ObservableCollection<UploadFileItem> _emissionStandardImages;
        public ObservableCollection<UploadFileItem> EmissionStandardImages
        {
            get { return _emissionStandardImages; }
            set
            {
                SetProperty(ref _emissionStandardImages, value);
            }
        }

        private string _carBrandModel;
        [Display(Name = "品牌型号")]
        [StringLength(50, ErrorMessage = "{0}超长:{1}")]
        public string CarBrandModel
        {
            get { return _carBrandModel; }
            set
            {
                SetProperty(ref _carBrandModel, value);
            }
        }

        private string _carNo;
        [Display(Name = "车牌号")]
        [Required(ErrorMessage = "{0}必填")]
        [StringLength(50, ErrorMessage = "{0}超长:{1}")]
        [AJFormCodeField]
        public string CarNo
        {
            get { return _carNo; }
            set
            {
                SetProperty(ref _carNo, value);
                SaveCmd.RaiseCanExecuteChanged();
            }
        }

        private string _cardNo;
        /// <summary>
        /// 卡号,用于读卡器识别车牌
        /// </summary>
        [MaxLength(100)]
        public string CardNo
        {
            get { return _cardNo; }
            set
            {
                SetProperty(ref _cardNo, value);
            }
        }

        private CarPlateColor _plateColor;
        /// <summary>
        /// 号牌颜色
        /// </summary>
        public CarPlateColor PlateColor
        {
            get { return _plateColor; }
            set
            {
                SetProperty(ref _plateColor, value);
            }
        }

        private VehicleType _vehicleType;
        /// <summary>
        /// 车辆种类
        /// </summary>
        public VehicleType VehicleType
        {
            get { return _vehicleType; }
            set
            {
                SetProperty(ref _vehicleType, value);
            }
        }

        private EmissionStandard _emissionStandard;
        /// <summary>
        /// 排放标准
        /// </summary>
        public EmissionStandard EmissionStandard
        {
            get { return _emissionStandard; }
            set
            {
                SetProperty(ref _emissionStandard, value);
            }
        }

        private string _engineManufacturer;
        /// <summary>
        /// 发动机生产厂
        /// </summary>
        public string EngineManufacturer
        {
            get { return _engineManufacturer; }
            set
            {
                SetProperty(ref _engineManufacturer, value);
            }
        }

        /// <summary>
        /// 发动机型号
        /// </summary>
        private string _engineModel;
        public string EngineModel
        {
            get { return _engineModel; }
            set
            {
                SetProperty(ref _engineModel, value);
            }
        }

        /// <summary>
        /// 发动机铭牌
        /// </summary>
        private ObservableCollection<UploadFileItem> _engineNameplate;
        public ObservableCollection<UploadFileItem> EngineNameplate
        {
            get { return _engineNameplate; }
            set
            {
                SetProperty(ref _engineNameplate, value);
            }
        }

        private string _engineNo;
        [Display(Name = "发动机号")]
        [StringLength(50, ErrorMessage = "{0}超长")]
        public string EngineNo
        {
            get { return _engineNo; }
            set
            {
                SetProperty(ref _engineNo, value);
            }
        }

        private string _envRegCode;
        /// <summary>
        /// 环保登记编码
        /// </summary>
        [Display(Name = "环保登记编码")]
        [StringLength(100, ErrorMessage = "{0}超长:{1}")]
        public string EnvRegCode
        {
            get { return _envRegCode; }
            set
            {
                SetProperty(ref _envRegCode, value);
            }
        }

        private DateTime? _expireDate;
        public DateTime? ExpireDate
        {
            get { return _expireDate; }
            set
            {
                SetProperty(ref _expireDate, value);
            }
        }

        private AJTableFormSchemaItemOptions _usageDescCode;
        /// <summary>
        /// 使用性质编号
        /// </summary>
        [Display(Name = "使用性质")]
        public AJTableFormSchemaItemOptions UsageDescCode
        {
            get { return _usageDescCode; }
            set
            {
                SetProperty(ref _usageDescCode, value);
            }
        }


        private AJTableFormSchemaItemOptions _fuelTypeCode;
        /// <summary>
        /// 燃料类型编码
        /// </summary>
        public AJTableFormSchemaItemOptions FuelTypeCode
        {
            get { return _fuelTypeCode; }
            set
            {
                SetProperty(ref _fuelTypeCode, value);
            }
        }

        private ObservableCollection<UploadFileItem> _machineEnvProtectionLabel;
        /// <summary>
        /// 机械环保信息标签
        /// </summary>
        public ObservableCollection<UploadFileItem> MachineEnvProtectionLabel
        {
            get { return _machineEnvProtectionLabel; }
            set
            {
                SetProperty(ref _machineEnvProtectionLabel, value);
            }
        }

        private string _machineModel;
        /// <summary>
        /// 机械型号
        /// </summary>
        public string MachineModel
        {
            get { return _machineModel; }
            set
            {
                SetProperty(ref _machineModel, value);
            }
        }

        private MachineType? _machineType;
        /// <summary>
        /// 机械种类
        /// </summary>
        public MachineType? MachineType
        {
            get { return _machineType; }
            set
            {
                SetProperty(ref _machineType, value);
            }
        }

        private DateTime? _mechanicalProdDate;
        /// <summary>
        /// 机械生产日期
        /// </summary>
        public DateTime? MechanicalProdDate
        {
            get { return _mechanicalProdDate; }
            set
            {
                SetProperty(ref _mechanicalProdDate, value);
            }
        }

        private ObservableCollection<UploadFileItem> _nameplate;
        /// <summary>
        /// 铭牌
        /// </summary>
        public ObservableCollection<UploadFileItem> Nameplate
        {
            get { return _nameplate; }
            set
            {
                SetProperty(ref _nameplate, value);
            }
        }

        private ObservableCollection<UploadFileItem> _carImage;
        /// <summary>
        /// 车辆图片
        /// </summary>
        public ObservableCollection<UploadFileItem> CarImage
        {
            get { return _carImage; }
            set
            {
                SetProperty(ref _carImage, value);
            }
        }

        private bool _networkingStatus;
        /// <summary>
        /// 联网状态
        /// </summary>
        public bool NetworkingStatus
        {
            get { return _networkingStatus; }
            set
            {
                SetProperty(ref _networkingStatus, value);
            }
        }

        private string _owner;
        /// <summary>
        /// 车辆所有人(单位)
        /// </summary>
        [Display(Name = "车辆所有人(单位)")]
        [StringLength(120, ErrorMessage = "{0}超长:{1}")]
        public string Owner
        {
            get { return _owner; }
            set
            {
                SetProperty(ref _owner, value);
            }
        }

        private string _pin;
        /// <summary>
        /// 机械环保代码(产品识别码)PIN
        /// </summary>
        [Display(Name = "机械环保代码")]
        [StringLength(100, ErrorMessage = "{0}超长:{1}")]
        public string PIN
        {
            get { return _pin; }
            set
            {
                SetProperty(ref _pin, value);
            }
        }

        private DateTime? _productionDate;
        /// <summary>
        /// 生产日期
        /// </summary>
        public DateTime? ProductionDate
        {
            get { return _productionDate; }
            set
            {
                SetProperty(ref _productionDate, value);
            }
        }

        private DateTime? _latestInspectionDate;
        /// <summary>
        /// 最新年检日期
        /// </summary>
        public DateTime? LatestInspectionDate
        {
            get { return _latestInspectionDate; }
            set
            {
                SetProperty(ref _latestInspectionDate, value);
            }
        }

        private DateTime? _regDate;
        /// <summary>
        /// 注册日期
        /// </summary>
        public DateTime? RegDate
        {
            get { return _regDate; }
            set
            {
                SetProperty(ref _regDate, value);
            }
        }

        private string _teamName;
        /// <summary>
        /// 车队名称
        /// </summary>
        [Display(Name = "车队名称")]
        [StringLength(50, ErrorMessage = "{0}超长:{1}")]
        public string TeamName
        {
            get { return _teamName; }
            set
            {
                SetProperty(ref _teamName, value);
            }
        }

        private AJTableFormSchemaItemOptions _truckTypeCode;
        /// <summary>
        /// 货车车辆类型编码, SystemDictionary.Code
        /// </summary>
        [Display(Name = "货车类型")]
        public AJTableFormSchemaItemOptions TruckTypeCode
        {
            get { return _truckTypeCode; }
            set
            {
                SetProperty(ref _truckTypeCode, value);
            }
        }

        private AJTableFormSchemaItemOptions _typeId;
        [Display(Name = "类型")]
        [Required(ErrorMessage = "{0}必填")]
        public AJTableFormSchemaItemOptions TypeId
        {
            get { return _typeId; }
            set
            {
                SetProperty(ref _typeId, value);
                SaveCmd.RaiseCanExecuteChanged();
                if (_formContentCtrl != null)
                {
                    if (_userCtrl != null)
                    {
                        var selector = _userCtrl.FindResource("formTemplateSelector") as CarFormTemplateSelector;
                        _formContentCtrl.ContentTemplate = selector.SelectTemplate(value, _formContentCtrl);
                        _formContentCtrl.Visibility = Visibility.Visible;
                    }
                }
            }
        }

        private AJTableFormSchemaItemOptions _carPrefix;
        [Display(Name = "车牌前缀")]
        [Required(ErrorMessage = "{0}必填")]
        public AJTableFormSchemaItemOptions CarPrefix
        {
            get { return _carPrefix; }
            set
            {
                SetProperty(ref _carPrefix, value);
                SaveCmd.RaiseCanExecuteChanged();
            }
        }

        private string _vin;
        [Display(Name = "VIN")]
        [StringLength(50, ErrorMessage = "{0}超长")]
        public string VIN
        {
            get { return _vin; }
            set
            {
                SetProperty(ref _vin, value);
            }
        }

        private string _isOwnedByCompany;
        /// <summary>
        /// 是否企业自有车辆
        /// </summary>
        [Display(Name = "是否企业自有车辆")]
        [StringLength(10, ErrorMessage = "{0}超长")]      
        public string IsOwnedByCompany 
        {
            set => SetProperty(ref _isOwnedByCompany, value); 
            get => _isOwnedByCompany;
        }

        private ObservableCollection<UploadFileItem> _vehicleLicense;
        public ObservableCollection<UploadFileItem> VehicleLicense
        {
            get { return _vehicleLicense; }
            set
            {
                SetProperty(ref _vehicleLicense, value);
            }
        }


        private ObservableCollection<AJTableFormSchemaItemOptions> _typeOptions;
        public ObservableCollection<AJTableFormSchemaItemOptions> TypeOptions
        {
            get { return _typeOptions; }
            set
            {
                SetProperty(ref _typeOptions, value);
            }
        }

        private Dictionary<string, CarPlateColor> _plateColorOptions;
        public Dictionary<string, CarPlateColor> PlateColorOptions
        {
            get { return _plateColorOptions; }
            set
            {
                SetProperty(ref _plateColorOptions, value);
            }
        }

        private Dictionary<string, MachineType> _machineTypeOptions;
        public Dictionary<string, MachineType> MachineTypeOptions
        {
            get { return _machineTypeOptions; }
            set
            {
                SetProperty(ref _machineTypeOptions, value);
            }
        }

        private Dictionary<string, VehicleType> _vehicleTypeOptions;
        public Dictionary<string, VehicleType> VehicleTypeOptions
        {
            get { return _vehicleTypeOptions; }
            set
            {
                SetProperty(ref _vehicleTypeOptions, value);
            }
        }

        private Dictionary<string, EmissionStandard> _emissionStandardOptions;
        public Dictionary<string, EmissionStandard> EmissionStandardOptions
        {
            get { return _emissionStandardOptions; }
            set
            {
                SetProperty(ref _emissionStandardOptions, value);
            }
        }

        private ObservableCollection<AJTableFormSchemaItemOptions> _fuelTypeOptions;
        public ObservableCollection<AJTableFormSchemaItemOptions> FuelTypeOptions
        {
            get { return _fuelTypeOptions; }
            set
            {
                SetProperty(ref _fuelTypeOptions, value);
            }
        }

        private ObservableCollection<AJTableFormSchemaItemOptions> _truckTypeOptions;
        public ObservableCollection<AJTableFormSchemaItemOptions> TruckTypeOptions
        {
            get { return _truckTypeOptions; }
            set
            {
                SetProperty(ref _truckTypeOptions, value);
            }
        }

        private ObservableCollection<AJTableFormSchemaItemOptions> _usageDescCodeOptions;
        public ObservableCollection<AJTableFormSchemaItemOptions> UsageDescCodeOptions
        {
            get { return _usageDescCodeOptions; }
            set
            {
                SetProperty(ref _usageDescCodeOptions, value);
            }
        }

        private ObservableCollection<AJTableFormSchemaItemOptions> _carPreFixOptions;
        public ObservableCollection<AJTableFormSchemaItemOptions> CarPreFixOptions
        {
            get { return _carPreFixOptions; }
            set
            {
                SetProperty(ref _carPreFixOptions, value);
            }
        }

        private ObservableCollection<string> _ownedbycompanyoptions;
        public ObservableCollection<string> OwnedByCompanyOptions
        {
            get => _ownedbycompanyoptions;
            set => SetProperty(ref _ownedbycompanyoptions, value);
        } 

        private DelegateCommand<object> _outGoodsNameSelectionChangedCmd;
        public DelegateCommand<object> OutGoodsNameSelectionChangedCmd =>
            _outGoodsNameSelectionChangedCmd ?? (_outGoodsNameSelectionChangedCmd = new DelegateCommand<object>(ExecuteOutGoodsNameSelectionChangedCmd));

        void ExecuteOutGoodsNameSelectionChangedCmd(object parameter)
        {
            ExecuteGoodsNameSelectionChanged(parameter, false);
        }

        private DelegateCommand<object> _inGoodsNameSelectionChangedCmd;
        public DelegateCommand<object> InGoodsNameSelectionChangedCmd =>
            _inGoodsNameSelectionChangedCmd ?? (_inGoodsNameSelectionChangedCmd = new DelegateCommand<object>(ExecuteInGoodsNameSelectionChangedCmd));

        void ExecuteInGoodsNameSelectionChangedCmd(object parameter)
        {
            ExecuteGoodsNameSelectionChanged(parameter, true);
        }

        private void ExecuteGoodsNameSelectionChanged(object parameter, bool inGoods)
        {
            string option = null;
            if (parameter is SelectionChangedEventArgs eventArgs)
            {
                if (eventArgs.AddedItems != null && eventArgs.AddedItems.Count > 0)
                {
                    option = eventArgs.AddedItems[0] as string;
                }
            }
            else
            {
                option = parameter as string;
            }

            if (string.IsNullOrWhiteSpace(option))
            {
                return;
            }

            var weightVal = (_goodsSrouce.FirstOrDefault(p => p.Name == option)?.DefaultWeight).GetValueOrDefault();

            if (inGoods)
            {
                InGoodsVolume = weightVal;
            }
            else
            {
                OutGoodsVolume = weightVal;
            }
        }

        private DelegateCommand _resetSyncStatusCmd;
        public DelegateCommand ResetSyncStatusCmd =>
            _resetSyncStatusCmd ?? (_resetSyncStatusCmd = new DelegateCommand(ExecuteResetSyncStatusCmd));

        void ExecuteResetSyncStatusCmd()
        {
            if (MessageBox.Show("请确保台账方不存在此数据,重置后会重新上传至台账", "提示", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
            {
                _form.Synchronized = Synchronized = false;

                MessageBox.Show("请确保数据无误后点击 [保存] 按钮上传至台账", "已重置同步标记", MessageBoxButton.OK);
            }
        }

        private DelegateCommand _saveCmd;
        public DelegateCommand SaveCmd =>
            _saveCmd ?? (_saveCmd = new DelegateCommand(ExecuteSaveCmdAsync, CanExecuteSaveCmd));

        async void ExecuteSaveCmdAsync()
        {
            if (!ValidateModel())
            {
                SaveCmd.RaiseCanExecuteChanged();

                AJCommonDialog.ShowDialog(new AJCommonDialogViewModel.AJCommonDialogParams
                {
                    Title = "提示",
                    Message = $"表单校验失败,请检查所填数据",
                    Detail = string.Join(";", ValidationErrorsByProperty.SelectMany(p => p.Value).Select(p => p.ToString()))
                });
                return;
            }

            var carNo = $"{CarPrefix.Value}{CarNo}";

            //if (!CommonRegex.CARNO.IsMatch(carNo))
            //{
            //    AJCommonDialog.ShowDialog(new AJCommonDialogViewModel.AJCommonDialogParams
            //    {
            //        Title = "提示",
            //        Message = "输入的车牌号格式有误"
            //    });
            //    return;
            //}

            Loading = true;

            // 固定车以上清空一些不要的表单
            if ((long)TypeId.Value >= (long)CarTypeEnum.固定车)
            {
                FuelTypeCode = null;
                TruckTypeCode = null;
                UsageDescCode = null;
            }
            if ((long)TypeId.Value == (long)CarTypeEnum.免检车)
            {
                EmissionStandard = EmissionStandard.未知;
            }

            _form.FuelTypeCode = FuelTypeCode?.Value as string;
            _form.FuelTypeName = FuelTypeCode?.Label;

            _form.TruckTypeCode = TruckTypeCode?.Value as string;
            _form.TruckTypeName = TruckTypeCode?.Label;

            _form.UsageDescCode = UsageDescCode?.Value as string;
            _form.UsageDescription = UsageDescCode?.Label;

            _form.TypeId = (long)TypeId.Value;
            _form.TypeName = TypeId.Label;

            var formProps = _form.GetType().GetRuntimeProperties();
            var modelProps = this.GetType().GetRuntimeProperties();

            foreach (var formProp in formProps)
            {
                var modelProp = modelProps.FirstOrDefault(p => p.Name == formProp.Name);
                if (modelProp == null ||
                    modelProp.Name == nameof(CarNo)
                    || formProp.Name == nameof(_form.Id)
                    || formProp.Name == nameof(_form.CreateDate)
                    || modelProp.Name == nameof(Synchronized)
                    || modelProp.Name == nameof(TypeId)
                    || modelProp.PropertyType == typeof(AJTableFormSchemaItemOptions))
                {
                    continue;
                }

                if (modelProp.PropertyType == typeof(ObservableCollection<UploadFileItem>))
                {
                    var formVal = modelProp.GetValue(this) as ObservableCollection<UploadFileItem>;
                    formProp.SetValue(_form, CommonUtil.AJSerializeObject(formVal.Select(p => Path.GetFileName(p.Url)).ToArray()));
                    continue;
                }
                formProp.SetValue(_form, modelProp.GetValue(this));
            }
            var addMode = _form.Id == 0;
            if (addMode)
            {
                if (db.Cars.Any(p => p.CarNo == carNo))
                {
                    FriendlyError("车牌号已存在");
                }

                _form.CarNo = carNo;
                _form.Id = YitIdHelper.NextId();
                _form.CreateDate = DateTime.Now;
                db.Cars.Add(_form);

            }
            else
            {
                if (_form.CarNo != carNo && db.Cars.Any(p => p.CarNo == carNo))
                {
                    FriendlyError("车牌号已存在");
                }

                _form.CarNo = carNo;
                _form.UpdateDate = DateTime.Now;
                db.Entry(_form).State = EntityState.Modified;

            }

            await db.SaveChangesAsync();

            // 将图片信息更新到关联的记录里面去 --阿吉 2025年1月13日11点42分
            await db.ShippingRecords.Where(p => p.CarNo == carNo)
                .ExecuteUpdateAsync(sp => sp.SetProperty(p => p.Nameplate, _form.Nameplate)
                .SetProperty(p => p.EngineNameplate, _form.EngineNameplate)
                .SetProperty(p => p.MachineEnvProtectionLabel, _form.MachineEnvProtectionLabel)
                .SetProperty(p => p.VehicleLicense, _form.VehicleLicense)
                .SetProperty(p => p.Attachments, _form.Attachments)
                .SetProperty(p => p.CarImage, _form.CarImage)
                .SetProperty(p => p.EmissionStandardImages, _form.EmissionStandardImages));


            if (_form.TypeId != (long)CarTypeEnum.免检车
                && _appointSvc.API is not DefaultAppointAPI)
            {
                var result = await _appointSvc.API.UploadCarInfoAsync(new CarInfoParams
                {
                    CarInfo = _form,
                    Operation = !_form.Synchronized ? DataOperationType.新增 : DataOperationType.更新
                });
                if (!result.Success)
                {
                    AJCommonDialog.ShowDialog(new AJCommonDialogViewModel.AJCommonDialogParams
                    {
                        Title = $"{_appointSvc.API.KeyDescription} 车辆信息同步接口提示",
                        Message = result.Message,
                        Detail = result.Data is Exception ex ? ex.StackTrace : string.Empty
                    });

                }

                //必须重新查出来保存, 否则报并发错误
                var dbRecord = db.Cars.FirstOrDefault(p => p.Id == _form.Id);
                dbRecord.Synchronized = result.Success;
                dbRecord.SyncResult = result.Success ? string.Empty : result.Message;
                dbRecord.UpdateDate = DateTime.Now;
                db.Entry(dbRecord).State = EntityState.Modified;
                db.SaveChanges();

                if (!result.Success)
                {
                    Loading = false;
                    return;
                }
            }
            else
            {
                var dbRecord = db.Cars.FirstOrDefault(p => p.Id == _form.Id);
                dbRecord.Synchronized = true;
                dbRecord.SyncResult = string.Empty;
                db.Entry(dbRecord).State = EntityState.Modified;
                db.SaveChanges();
            }

            Loading = false;

            RequestClose?.Invoke(new DialogResult(ButtonResult.OK));
        }

        bool CanExecuteSaveCmd()
        {
            return !HasErrors;
        }

        public string Title => string.Empty;

        public event Action<IDialogResult> RequestClose;

        public bool CanCloseDialog()
        {
            return true;
        }

        public void OnDialogClosed()
        {

        }

        public async void OnDialogOpened(IDialogParameters parameters)
        {
            parameters.TryGetValue<Car>("data", out var data);

            parameters.TryGetValue<ObservableCollection<AJTableFormSchemaItemOptions>>("typeOptions", out var typeOptions);

            OwnedByCompanyOptions = new ObservableCollection<string> { "是", "否" };

            typeOptions ??= new ObservableCollection<AJTableFormSchemaItemOptions>();

            if (typeOptions.Count == 0)
            {
                var typeSource = await db.CarTypes.Select(p => new
                {
                    p.Id,
                    p.Name
                }).AsNoTracking().ToListAsync();
                TypeOptions = new ObservableCollection<AJTableFormSchemaItemOptions>(typeSource.Select(p => new AJTableFormSchemaItemOptions
                {
                    Label = p.Name,
                    Value = p.Id
                }));
            }
            else
            {
                TypeOptions = typeOptions;
            }

            var fuelTypeOptions = await SystemDictionaryExt.GetSystemDictionariesAsync(db, SystemDictionaryExt.SystemDictionaryKey.燃料);

            FuelTypeOptions = new ObservableCollection<AJTableFormSchemaItemOptions>(fuelTypeOptions.Select(p => new AJTableFormSchemaItemOptions
            {
                Label = p.Name,
                Value = p.Code
            }));

            var truckTypeOptions = await SystemDictionaryExt.GetSystemDictionariesAsync(db, SystemDictionaryExt.SystemDictionaryKey.货车);

            TruckTypeOptions = new ObservableCollection<AJTableFormSchemaItemOptions>(truckTypeOptions.Select(p => new AJTableFormSchemaItemOptions
            {
                Label = p.Name,
                Value = p.Code
            }));

            var usageDescCodeOptions = await SystemDictionaryExt.GetSystemDictionariesAsync(db, SystemDictionaryExt.SystemDictionaryKey.使用性质);

            UsageDescCodeOptions = new ObservableCollection<AJTableFormSchemaItemOptions>(usageDescCodeOptions.Select(p => new AJTableFormSchemaItemOptions
            {
                Label = p.Name,
                Value = p.Code
            }));

            _goodsSrouce = db.Goods.AsNoTracking().OrderByDescending(p => p.Id).ToList();

            GoodsOptions = new ObservableCollection<string>(_goodsSrouce.Select(p => p.Name));

            var _carIdentityCfg = CarIdentificationConfigExt.GetCarIdentificationConfig(db);

            var customUploadFolder = _carIdentityCfg.ImageSavePath ?? CarIdentificationConfig.GetDefaultSavePath();

            UploadOptions.CustomUploadFolder = customUploadFolder;

            UploadOptions.BeforeFileDialogShowHandle = (picker) =>
            {
                if (CarPrefix == null || string.IsNullOrWhiteSpace(CarNo))
                {
                    MessageBox.Show("请先填写车牌号", "提示", MessageBoxButton.OK);
                    return false;
                }
                UploadOptions.CustomUploadFolder = Path.Combine(customUploadFolder, $"{CarPrefix.Value}{CarNo}");
                return true;
            };

            if (data != null)
            {
                _form = data;

                var prefix = _form.CarNo.ElementAtOrDefault(0).ToString();

                CarPrefix = CarPreFixOptions.FirstOrDefault(p => p.Label == prefix) ?? CarPreFixOptions.LastOrDefault();
                CarNo = string.Join("", _form.CarNo.Skip(1).ToArray());

                TypeId = TypeOptions.FirstOrDefault(p => (long)p.Value == _form.TypeId);
                FuelTypeCode = FuelTypeOptions.FirstOrDefault(p => p.Label == _form.FuelTypeName);
                TruckTypeCode = TruckTypeOptions.FirstOrDefault(p => p.Label == _form.TruckTypeName);
                UsageDescCode = UsageDescCodeOptions.FirstOrDefault(p => p.Label == _form.UsageDescription);
                var formProps = _form.GetType().GetRuntimeProperties();
                var modelProps = this.GetType().GetRuntimeProperties();

                foreach (var modelProp in modelProps)
                {
                    var formProp = formProps.FirstOrDefault(p => p.Name == modelProp.Name);
                    if (formProp == null ||
                        modelProp.Name == nameof(CarNo)
                        || modelProp.PropertyType == typeof(AJTableFormSchemaItemOptions))
                    {
                        continue;
                    }

                    if (modelProp.PropertyType == typeof(ObservableCollection<UploadFileItem>))
                    {
                        var formVal = CommonUtil.TryGetJSONObject<string[]>(formProp.GetValue(_form) as string) ?? Array.Empty<string>();

                        var imagesValue = new ObservableCollection<UploadFileItem>(formVal.Select(p => new UploadFileItem(_carIdentityCfg.CompleteFileUrl(_form.CarNo, p))));

                        modelProp.SetValue(this, imagesValue);
                        continue;
                    }
                    modelProp.SetValue(this, formProp.GetValue(_form));
                }
            }
            else
            {
                CarPrefix = CarPreFixOptions.LastOrDefault();
                TypeId = TypeOptions.FirstOrDefault();
                FuelTypeCode = FuelTypeOptions.FirstOrDefault();
                TruckTypeCode = TruckTypeOptions.FirstOrDefault();
                UsageDescCode = UsageDescCodeOptions.FirstOrDefault();
            }

            DialogTitle = data == null ? $"新增车辆" : $"编辑 {data.CarNo}";
        }

        private DelegateCommand<ContentControl> _formContentLoadedCmd;
        public DelegateCommand<ContentControl> FormContentLoadedCmd =>
            _formContentLoadedCmd ?? (_formContentLoadedCmd = new DelegateCommand<ContentControl>(ExecuteFormContentLoadedCmd));

        void ExecuteFormContentLoadedCmd(ContentControl parameter)
        {
            _formContentCtrl = parameter;
        }

        private DelegateCommand<UserControl> _userCtrlLoadedCmd;
        public DelegateCommand<UserControl> UserCtrlLoadedCmd =>
            _userCtrlLoadedCmd ?? (_userCtrlLoadedCmd = new DelegateCommand<UserControl>(ExecuteUserCtrlLoadedCmd));

        void ExecuteUserCtrlLoadedCmd(UserControl parameter)
        {
            _userCtrl = parameter;
        }

        private ContentControl _formContentCtrl;
        private UserControl _userCtrl;
        private DbService db;
        private AJGlobalExceptionResolvedEvent _globalExceptionEvt;
        private AppointAPISvc _appointSvc;

        public CarFormViewModel(DbService dbIns, AppointAPISvc appointAPISvc, IEventAggregator eventAggregator)
        {
            _form = new Car();
            _appointSvc = appointAPISvc;
            VehicleLicense = new ObservableCollection<UploadFileItem>();
            Attachments = new ObservableCollection<UploadFileItem>();
            EngineNameplate = new ObservableCollection<UploadFileItem>();
            MachineEnvProtectionLabel = new ObservableCollection<UploadFileItem>();
            EmissionStandardImages = new ObservableCollection<UploadFileItem>();
            Nameplate = new ObservableCollection<UploadFileItem>();
            CarImage = new ObservableCollection<UploadFileItem>();
            _globalExceptionEvt = eventAggregator.GetEvent<AJGlobalExceptionResolvedEvent>();
            _globalExceptionEvt.Subscribe(() =>
            {
                Loading = false;
            });
            db = dbIns;
            UploadOptions = new UploadConfig
            {
                Limit = 1,
                Height = 120,
                Width = 120,
                Text = "上传",
            };
            CarPreFixOptions = new ObservableCollection<AJTableFormSchemaItemOptions>(CommonUtil.CARNOPREFIX.Select(p => new AJTableFormSchemaItemOptions
            {
                Label = p,
                Value = p == "无" ? "" : p
            }));

            PlateColorOptions = CommonUtil.EnumToDictionary<CarPlateColor>(null);
            EmissionStandardOptions = CommonUtil.EnumToDictionary<EmissionStandard>(null);
            MachineTypeOptions = CommonUtil.EnumToDictionary<MachineType>(null);
            VehicleTypeOptions = CommonUtil.EnumToDictionary<VehicleType>(null);

            DialogTitle = string.Empty;
        }
    }
}
